iT邦幫忙

2024 iThome 鐵人賽

DAY 23
0

這篇我們來實作主要移動棋子的方法move(),以及發生移動事件後會使用到的其他方法,接著實作關於士兵升變的方法


move()

首先判斷遊戲是否結束,再通過一些局面的判斷,然後產生棋譜資料,再將修改後的棋盤資料上傳到資料庫,最後初始化本回合暫存的所有變數

public void move(){
        new Thread(() -> {
            // 判斷遊戲是否結束
            if(!isGameFinish()){
                // 如果有王車易位,則修改指定格的棋子
                isCastling();
                // 處理兵的特殊情況
                disposePawn();
                // 產生棋譜資料
                moveData(String.valueOf(playerChessboardData.getStringBoardData(startChessman))
                        ,String.valueOf(playerChessboardData.getStringBoardData(stopChessman)));
                // 判斷是否可升變
                isPromotion();
                // 修改棋盤資料,將目標格棋子改為原起始格棋子,原起始格棋子改為空格
                chessboardData.put(String.valueOf(playerChessboardData.getStringBoardData(stopChessman)),String.valueOf(chessboardData.get(playerChessboardData.getStringBoardData(startChessman))));
                chessboardData.put(String.valueOf(playerChessboardData.getStringBoardData(startChessman)),"  ");

                dbp.uploadData(roomKey,"PawnMove1",pawnMove1);
                // 上傳棋盤資料
                if(isPromotion == false){
                    chessmanMoveData.put(String.valueOf(turn),moveData);
                    dbp.uploadData(roomKey,"ChessmanMoveData",chessmanMoveData);
                    dbp.uploadData(roomKey,"ChessboardData",chessboardData);
                    dbp.uploadData(roomKey,"MoveState","black");
                    // 回合數增加
                    turn += 1;
                    dbp.uploadData(roomKey,"Turn",String.valueOf(turn));
                }
            }

            runOnUiThread(() -> {
                // 清除上回合所有移動資料
                clearData();
            });
        }).start();
    }

isGameFinish()

判斷遊戲是否結束

public boolean isGameFinish(){
        Boolean isGameFinish=false;
        // 如果吃的棋是國王則遊戲結束
        if(chessboardData.get(playerChessboardData.getStringBoardData(stopChessman)).equals("bK")){
            isGameFinish = true;
            dbp.uploadData(roomKey,"WinPlayer","white");

            // 產生棋譜資料
            moveData(String.valueOf(playerChessboardData.getStringBoardData(startChessman))
                    ,String.valueOf(playerChessboardData.getStringBoardData(stopChessman)));
            moveData = moveData + " #";
            // 修改棋盤資料,將目標格棋子改為原起始格棋子,原起始格棋子改為空格
            chessboardData.put(String.valueOf(playerChessboardData.getStringBoardData(stopChessman)),String.valueOf(chessboardData.get(playerChessboardData.getStringBoardData(startChessman))));
            chessboardData.put(String.valueOf(playerChessboardData.getStringBoardData(startChessman)),"  ");
            chessmanMoveData.put(String.valueOf(turn),moveData);
            dbp.uploadData(roomKey,"ChessmanMoveData",chessmanMoveData);
            dbp.uploadData(roomKey,"ChessboardData",chessboardData);
        }
        return isGameFinish;
    }

isCastling()

判斷是否接收到王車易位的指標,若有則同時移動城堡

public void isCastling(){
        if(castling.equals("leftCastling")){
            chessboardData.put("d1","wR");
            chessboardData.put("a1","  ");
        }else if(castling.equals("rightCastling")){
            chessboardData.put("f1","wR");
            chessboardData.put("h1","  ");
        }
    }

disposePawn()

處理士兵的特殊走法

public void disposePawn(){
        // 如果可吃過路兵,將對方兵變為空格
        if(!(inPassing.equals(""))){
            chessboardData.put(inPassing,"  ");
        }
        // 將自己的兵標記清除
        for(int i=1;i<=8;i++){
            pawnMove1.put(coordinate_a[i]+"4",false);
        }
        // 如果有兵起始走2格,將該兵做標記
        if(!(moveTwoStep.equals(""))){
            pawnMove1.put(moveTwoStep,true);
        }
    }

moveData()

產生棋譜資料

public void moveData(String start,String stop){
        // moveData = 棋種 + 起始座標
        moveData = chessboardData.get(start).toString().charAt(1) + start;
        // 判斷是移動到空格還是吃棋
        if(chessboardData.get(stop).equals("  ")){
            moveData = moveData + " > ";
        } else if (String.valueOf(chessboardData.get(stop).toString().charAt(0)).equals("b")) {
            moveData = moveData + " X ";
        }
        // moveData = 棋種 + 起始座標 X,> 目標座標
        moveData = moveData + stop;
    }

isPromotion()

判斷士兵是否可進行升變,若可以則跳出選擇升變的dialog

public void isPromotion(){
        // 判斷是否有兵移動到最底橫列
        if(chessboardData.get(String.valueOf(playerChessboardData.getStringBoardData(startChessman))).equals("wP")
                && stopChessman/8==0){
            isPromotion = true;
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    // 顯示升變選擇
                    showPromotionDialog(stopChessman);
                }
            });
        }
    }

clearData()

初始化暫存的變數

public void clearData(){
        startChessman = 99;
        stopChessman = 99;
        castling = "";
        moveTwoStep = "";
        inPassing = "";
        getCount=0;
        isPromotion = false;
        for(int i=0;i<64;i++){
            chessmanSelect.get(i).setBackgroundResource(R.drawable.blank);
        }
    }

升變

升變是士兵的特殊走法之一,我們在這邊實作簡單的對話框來實現讓使用者選擇欲升變的棋種

  • showPromotionDialog()
public void showPromotionDialog(int p){
        // 創建升變Dialog並設置自定義布局
        Dialog dialog = new Dialog(this);
        dialog.setContentView(R.layout.white_promotion_dialog_item);
        // 獲取自定義布局中的UI元素
        TextView tv_q = dialog.findViewById(R.id.tv_q);
        TextView tv_b = dialog.findViewById(R.id.tv_b);
        TextView tv_n = dialog.findViewById(R.id.tv_n);
        TextView tv_r = dialog.findViewById(R.id.tv_r);
        Button btn_promotion_q = dialog.findViewById(R.id.btn_promotion_q);
        Button btn_promotion_b = dialog.findViewById(R.id.btn_promotion_b);
        Button btn_promotion_n = dialog.findViewById(R.id.btn_promotion_n);
        Button btn_promotion_r = dialog.findViewById(R.id.btn_promotion_r);
        Button btn_submit = dialog.findViewById(R.id.btn_submit);

        promotion = "";
        btn_submit.setEnabled(false);
        btn_submit.setBackgroundResource(R.drawable.whitebackground_grayline);
        btn_promotion_q.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tv_q.setBackgroundResource(R.drawable.blank);
                tv_b.setBackgroundResource(R.drawable.blank);
                tv_n.setBackgroundResource(R.drawable.blank);
                tv_r.setBackgroundResource(R.drawable.blank);
                if(promotion.equals("Q")){
                    promotion="";
                }else{
                    promotion="Q";
                    tv_q.setBackgroundResource(R.drawable.redline);
                }
                if(promotion.equals("")){
                    btn_submit.setEnabled(false);
                    btn_submit.setBackgroundResource(R.drawable.whitebackground_grayline);
                }else{
                    btn_submit.setEnabled(true);
                    btn_submit.setBackgroundResource(R.drawable.redbackground_blackline);
                }
            }
        });
        btn_promotion_b.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tv_q.setBackgroundResource(R.drawable.blank);
                tv_b.setBackgroundResource(R.drawable.blank);
                tv_n.setBackgroundResource(R.drawable.blank);
                tv_r.setBackgroundResource(R.drawable.blank);
                if(promotion.equals("B")){
                    promotion="";
                }else{
                    promotion="B";
                    tv_b.setBackgroundResource(R.drawable.redline);
                }
                if(promotion.equals("")){
                    btn_submit.setEnabled(false);
                    btn_submit.setBackgroundResource(R.drawable.whitebackground_grayline);
                }else{
                    btn_submit.setEnabled(true);
                    btn_submit.setBackgroundResource(R.drawable.redbackground_blackline);
                }
            }
        });
        btn_promotion_n.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tv_q.setBackgroundResource(R.drawable.blank);
                tv_b.setBackgroundResource(R.drawable.blank);
                tv_n.setBackgroundResource(R.drawable.blank);
                tv_r.setBackgroundResource(R.drawable.blank);
                if(promotion.equals("N")){
                    promotion="";
                }else{
                    promotion="N";
                    tv_n.setBackgroundResource(R.drawable.redline);
                }
                if(promotion.equals("")){
                    btn_submit.setEnabled(false);
                    btn_submit.setBackgroundResource(R.drawable.whitebackground_grayline);
                }else{
                    btn_submit.setEnabled(true);
                    btn_submit.setBackgroundResource(R.drawable.redbackground_blackline);
                }
            }
        });
        btn_promotion_r.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tv_q.setBackgroundResource(R.drawable.blank);
                tv_b.setBackgroundResource(R.drawable.blank);
                tv_n.setBackgroundResource(R.drawable.blank);
                tv_r.setBackgroundResource(R.drawable.blank);
                if(promotion.equals("R")){
                    promotion="";
                }else{
                    promotion="R";
                    tv_r.setBackgroundResource(R.drawable.redline);
                }
                if(promotion.equals("")){
                    btn_submit.setEnabled(false);
                    btn_submit.setBackgroundResource(R.drawable.whitebackground_grayline);
                }else{
                    btn_submit.setEnabled(true);
                    btn_submit.setBackgroundResource(R.drawable.redbackground_blackline);
                }
            }
        });
        btn_submit.setOnClickListener(v -> {
            dialog.dismiss();
            moveData = moveData +" ("+promotion+")";
            new Thread(() ->{
                chessmanMoveData.put(String.valueOf(turn),moveData);
                chessboardData.put(playerChessboardData.getStringBoardData(p),"w"+promotion);
                dbp.uploadData(roomKey,"ChessboardData",chessboardData);
                dbp.uploadData(roomKey,"ChessmanMoveData",chessmanMoveData);
                dbp.uploadData(roomKey,"MoveState","black");
                // 回合數增加
                turn += 1;
                dbp.uploadData(roomKey,"Turn",String.valueOf(turn));
            }).start();
        });
        dialog.setCancelable(false);
        dialog.setCanceledOnTouchOutside(false);
        dialog.show();
    }
  • white_promotion_dialog_item.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="250dp"
    android:layout_height="250dp"
    android:layout_gravity="center"
    android:background="@drawable/brownbackground_grayline">

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@drawable/brownline"
        android:gravity="center"
        android:text="請選擇一個棋種"
        android:textColor="@color/black"
        android:textStyle="bold"
        app:layout_constraintBottom_toTopOf="@+id/guideline50"
        app:layout_constraintEnd_toStartOf="@+id/guideline94"
        app:layout_constraintStart_toStartOf="@+id/guideline92"
        app:layout_constraintTop_toTopOf="@+id/guideline135" />

    <Button
        android:id="@+id/btn_submit"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@drawable/redbackground_blackline"
        android:gravity="center"
        android:text="確定"
        android:textColor="@color/white"
        android:textStyle="bold"
        app:backgroundTint="@null"
        app:layout_constraintBottom_toTopOf="@+id/guideline101"
        app:layout_constraintEnd_toStartOf="@+id/guideline94"
        app:layout_constraintStart_toStartOf="@+id/guideline92"
        app:layout_constraintTop_toTopOf="@+id/guideline66" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline50"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.2" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline51"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.5" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline66"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.8" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline67"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.2" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline65"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.5" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline68"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.8" />

    <TextView
        android:id="@+id/tv_q"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/guideline51"
        app:layout_constraintEnd_toStartOf="@+id/guideline65"
        app:layout_constraintStart_toStartOf="@+id/guideline67"
        app:layout_constraintTop_toTopOf="@+id/guideline50" />

    <TextView
        android:id="@+id/tv_b"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/guideline51"
        app:layout_constraintEnd_toStartOf="@+id/guideline68"
        app:layout_constraintStart_toStartOf="@+id/guideline65"
        app:layout_constraintTop_toTopOf="@+id/guideline50" />

    <TextView
        android:id="@+id/tv_n"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/guideline66"
        app:layout_constraintEnd_toStartOf="@+id/guideline65"
        app:layout_constraintStart_toStartOf="@+id/guideline67"
        app:layout_constraintTop_toTopOf="@+id/guideline51" />

    <TextView
        android:id="@+id/tv_r"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/guideline66"
        app:layout_constraintEnd_toStartOf="@+id/guideline68"
        app:layout_constraintStart_toStartOf="@+id/guideline65"
        app:layout_constraintTop_toTopOf="@+id/guideline51" />

    <Button
        android:id="@+id/btn_promotion_q"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@drawable/white_queen"
        app:backgroundTint="@null"
        app:layout_constraintBottom_toTopOf="@+id/guideline51"
        app:layout_constraintEnd_toStartOf="@+id/guideline65"
        app:layout_constraintStart_toStartOf="@+id/guideline67"
        app:layout_constraintTop_toTopOf="@+id/guideline50" />

    <Button
        android:id="@+id/btn_promotion_b"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@drawable/white_bishop"
        app:backgroundTint="@null"
        app:layout_constraintBottom_toTopOf="@+id/guideline51"
        app:layout_constraintEnd_toStartOf="@+id/guideline68"
        app:layout_constraintStart_toStartOf="@+id/guideline65"
        app:layout_constraintTop_toTopOf="@+id/guideline50" />

    <Button
        android:id="@+id/btn_promotion_n"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@drawable/white_knight"
        app:backgroundTint="@null"
        app:layout_constraintBottom_toTopOf="@+id/guideline66"
        app:layout_constraintEnd_toStartOf="@+id/guideline65"
        app:layout_constraintStart_toStartOf="@+id/guideline67"
        app:layout_constraintTop_toTopOf="@+id/guideline51" />

    <Button
        android:id="@+id/btn_promotion_r"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@drawable/white_rook"
        app:backgroundTint="@null"
        app:layout_constraintBottom_toTopOf="@+id/guideline66"
        app:layout_constraintEnd_toStartOf="@+id/guideline68"
        app:layout_constraintStart_toStartOf="@+id/guideline65"
        app:layout_constraintTop_toTopOf="@+id/guideline51" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline92"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.1" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline94"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.9" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline101"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.97" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline135"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.03" />

</androidx.constraintlayout.widget.ConstraintLayout>

成果:


至此,整個主程式就算是大功告成,下一篇開始我們來實作設置(setting)這個額外功能


上一篇
【DAY 22】activity - Player1ChessGame - isEnableMove
下一篇
【DAY 24】activity - setting - VolumeChangeReceiver
系列文
基於Firebase整合生成式AI研究開發雙人國際象棋系統(Based on Firebase and AI to research chess system)30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言